﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Text.RegularExpressions;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;

namespace WOWMultiPlay
{
    public static class Helper_Keyboard
    {
        private enum PressKeyOption
        {
            KeyDown,
            KeyDownUp,
        }

        public static void SendKeys_NewThread(IntPtr hWnd, Button ProfileWinFormButton)
        {
            Helper_Profile.Profile.Button ProfileButton = (Helper_Profile.Profile.Button)ProfileWinFormButton.Tag;

            Thread SendKeysThread = new Thread(delegate() { SendKeys(hWnd, ProfileWinFormButton); });
            SendKeysThread.IsBackground = true;
            SendKeysThread.Start();

            ProfileButton.SendKeysThread = SendKeysThread;
        }

        private static void SendKeys(IntPtr hWnd, Button ProfileWinFormButton)
        {
            Helper_Profile.Profile.Button ProfileButton = (Helper_Profile.Profile.Button)ProfileWinFormButton.Tag;

            SendKeys(hWnd, ProfileButton.KeyQuery, ProfileButton.Repeat, ProfileButton.RepeatInterval);

            ProfileButton.SendKeysThread = null;
            Helper_Thread.SetButtonForeColor(ProfileWinFormButton, Setting_Global.NormalButtonFontColor);
        }

        private static void SendKeys(IntPtr hWnd, string KeysQuery, int Repeat, Helper_Profile.Profile.Button.TimeInterval RepeatInterval)
        {
            int RepeatCount = 0;

            while (Repeat == 0 || RepeatCount < Repeat)
            {
                string[] KeyArray = GetKeyArray(KeysQuery);

                foreach (string Key in KeyArray)
                {
                    string[] KeyQueryArgu = Key.Split(new char[] { ',' });

                    PressKeyOption PressKeyOption = PressKeyOption.KeyDownUp;

                    if (KeyQueryArgu.Length == 2)
                    {
                        switch (KeyQueryArgu[1])
                        {
                            case "D":
                                PressKeyOption = PressKeyOption.KeyDown;
                                break;
                            case "DU":
                                PressKeyOption = PressKeyOption.KeyDownUp;
                                break;
                            default:
                                break;
                        }

                        SendKey(hWnd, GetVK(KeyQueryArgu[0]), PressKeyOption);
                    }
                    else
                    {
                        SendKey(hWnd, GetVK(Key), PressKeyOption);
                    }
                }

                if (Repeat != 0)
                    RepeatCount++;

                if (Repeat != 1)
                    Helper_Timer.Sleep(RepeatInterval);
            }
        }

        private static void SendKey(IntPtr hWnd, int Key, PressKeyOption keyOption)
        {
            Helper_Win32API.PostMessageA(hWnd, Helper_Win32API.WM.WM_KEYDOWN, Key, 0);
            
            if (keyOption == PressKeyOption.KeyDownUp)
            {
                Helper_Timer.Sleep(new Helper_Profile.Profile.Button.TimeInterval(Setting_Global.Interval_KeyDown_Up));
                Helper_Win32API.PostMessageA(hWnd, Helper_Win32API.WM.WM_KEYUP, Key, 0);
            }

            Helper_Timer.Sleep(new Helper_Profile.Profile.Button.TimeInterval(Setting_Global.Interval_KeyPress));
        }

        private static string[] GetKeyArray(string KeysQuery)
        {
            Regex KeysQueryRegex = new Regex("{((?:.|\n)*?)}");
            MatchCollection KeysQueryMatches = KeysQueryRegex.Matches(KeysQuery);

            if (KeysQueryMatches.Count > 0)
            {
                string[] KeyArray = new string[KeysQueryMatches.Count];

                for (int i = 0; i < KeysQueryMatches.Count; i++)
                {
                    KeyArray[i] = KeysQueryMatches[i].Groups[1].Value;
                }

                return KeyArray;
            }
            else
            {
                return new string[0];
            }
        }

        private static int GetVK(string Key)
        {
            Assembly Asm = Assembly.GetExecutingAssembly();
            Type TypeWin32API = Asm.GetType("WOWMultiPlay.Helper_Win32API");
            Type TypeVK = TypeWin32API.GetNestedType("VK");

            FieldInfo FI = TypeVK.GetField(Key);
            return (int)FI.GetValue(null);
        }
    }
}